package com.xinzhidi.web.netty.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.utils.DateUtils;
import com.xinzhidi.web.alarmSetting.domain.AlarmSetting;
import com.xinzhidi.web.alarmSetting.service.AlarmSettingService;
import com.xinzhidi.web.build.domain.BuildUnit;
import com.xinzhidi.web.build.domain.CBuild;
import com.xinzhidi.web.build.service.IBuildUnitService;
import com.xinzhidi.web.build.service.ICBuildService;
import com.xinzhidi.web.equipment.domain.Equipment;
import com.xinzhidi.web.equipment.service.EquipmentService;
import com.xinzhidi.web.equipmentAlarm.domain.EquipmentAlarm;
import com.xinzhidi.web.equipmentAlarm.service.EquipmentAlarmService;
import com.xinzhidi.web.house.domain.Household;
import com.xinzhidi.web.house.service.IHouseholdService;
import com.xinzhidi.web.netty.entity.*;
import com.xinzhidi.web.plot.domain.entity.CPlot;
import com.xinzhidi.web.plot.service.ICPlotService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 更新数据service
 *
 * @author cx
 * @date 2023-06-17
 */
@Service
@RequiredArgsConstructor
public class NettyUpdateService {


    private final IHouseholdService householdService;

    private final IBuildUnitService buildUnitService;

    private final EquipmentService equipmentService;

    private final ICBuildService cBuildService;


    private final EquipmentAlarmService equipmentAlarmService;

    private final AlarmSettingService alarmSettingService;

    private final ICBuildService buildService;

    private final ICPlotService plotService;

    private final AgreementHeatService heatService;

    private final AgreementHeatHistoryService heatHistoryService;

    private final AgreementUnitValveHistoryService unitValveHistoryService;

    private final AgreementBuildValveHistoryService buildValveHistoryService;

    private final AgreementUnitValveService unitValveService;

    private final AgreementBuildValveService buildValveService;

    /**
     * 根据住户数据更新
     *
     * @param equipment
     * @param map
     */
    public void updateHouseholdData(Equipment equipment, Map<String, Object> map) {
        Household household = householdService.getById(equipment.getHouseholdId());
        UpdateWrapper<Household> householdUpdateWrapper = new UpdateWrapper<>();
        String protocolType = equipment.getProtocolType();
        if (protocolType.equals(AgreementConstants.AgreementType.HOUSEHOLD_VALVE) || protocolType.equals(AgreementConstants.AgreementType.SEAHORSE_VALVE_METER)) {
            //阀门开度
            Integer valveOpen = Double.valueOf(map.get("valveOpen").toString()).intValue();
            if (valveOpen.compareTo(0) < 0 || valveOpen.compareTo(100) > 0) {
                LambdaQueryWrapper<AlarmSetting> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(AlarmSetting::getAlarmType, AgreementConstants.ExceptionType.TRANSFINITE_EXCEPTION);
                wrapper.eq(AlarmSetting::getIndexType, AgreementConstants.ControlTactics.ROOM_TEMPERATURE);
                AlarmSetting setting = alarmSettingService.getOne(wrapper);
                //阀门开度异常
                EquipmentAlarm alarm = new EquipmentAlarm();
                alarm.setPlotId(equipment.getLotId());
                alarm.setBuildId(equipment.getBuildId());
                alarm.setUnitId(equipment.getUnitId());
                alarm.setHouseholdId(equipment.getHouseholdId());
                alarm.setEquipmentId(equipment.getId());
                alarm.setAlarmSettingId(setting.getId());
                alarm.setHideOrPush(Integer.parseInt(setting.getPushStatus()));
                alarm.setPushNum(setting.getPushInterval());
                alarm.setRemark("设备【" + equipment.getEquipmentName() + "】开度超限异常");
                equipmentAlarmService.save(alarm);
                return;
            }
            householdUpdateWrapper.set("valve_open", valveOpen);
            householdUpdateWrapper.set("valve_read_time", DateUtils.getNowDate());
        } else {
            //瞬时流量
            BigDecimal velocityFlow = new BigDecimal(map.get("velocityFlow").toString());

            //瞬时热量
            BigDecimal thermalPower = new BigDecimal(map.get("thermalPower").toString());

            //累计热量
            BigDecimal currentHeatOrCold = new BigDecimal(map.get("currentHeatOrCold").toString());

            //累计流量
            BigDecimal totalFlow = new BigDecimal(map.get("totalFlow").toString());

            //供水温度
            BigDecimal waterSupplyTemperature = new BigDecimal(map.get("waterSupplyTemperature").toString());
            //回水温度
            BigDecimal returnWaterTemperature = new BigDecimal(map.get("returnWaterTemperature").toString());
            householdUpdateWrapper
                    .set(velocityFlow != null, "velocity_flow", velocityFlow)
                    .set(thermalPower != null, "thermal_power", thermalPower)
                    .set(currentHeatOrCold != null, "current_heat_or_cold", currentHeatOrCold)
                    .set(totalFlow != null, "total_flow", totalFlow)
                    .set(waterSupplyTemperature != null, "water_supply_temperature", waterSupplyTemperature)
                    .set(returnWaterTemperature != null, "return_water_temperature", returnWaterTemperature);
        }
        householdUpdateWrapper.eq("id", household.getId());
        householdService.update(householdUpdateWrapper);
        this.updateByHousehold(equipment);
    }

    /**
     * 根据住户数据更新数据(单元、楼栋、小区)
     *
     * @param equipment
     */
    public void updateByHousehold(Equipment equipment) {
        Map<String, Object> avgMap;
        String protocolType = equipment.getProtocolType();
        List<Equipment> buildUnitEquipmentList;
        List<Equipment> buildEquipmentList;
        Long unitId = equipment.getUnitId();
        Long buildId = equipment.getBuildId();
        Long plotId = equipment.getLotId();
        BuildUnit unit = buildUnitService.getById(unitId);
        CBuild build = buildService.getById(buildId);
        CPlot plot = plotService.getById(plotId);
        List<Household> householdList = householdService.list(Wrappers.<Household>lambdaQuery()
                .eq(Household::getUnit, unitId));

        if (protocolType.equals(AgreementConstants.AgreementType.HOUSEHOLD_VALVE) || protocolType.equals(AgreementConstants.AgreementType.SEAHORSE_VALVE_METER)) {
            //更新单元数据
            //判断该住户的楼栋是否有单元阀门，如果没有，则更新该单元所有住户数据至单元表，如果有，则不更新
            buildUnitEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                    .eq(Equipment::getUnitId, unitId)
                    .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.UNIT_VALVE));
            if (CollectionUtils.isEmpty(buildUnitEquipmentList)) {
                //获取单元下所有住户阀门开度平均值
                householdList = householdList.stream().filter(household -> household.getValveOpen() != null).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(householdList)) {
                    Integer sum = householdList.stream().mapToInt(Household::getValveOpen).sum();
                    Integer avgOpen = sum / householdList.size();
                    //更新单元阀门开度
                    unit.setValveOpen(avgOpen);
                    unit.setValveReadTime(DateUtils.getNowDate());
                    //新增单元阀门开度实时数据和历史数据
                    avgMap = new HashMap<>();
                    avgMap.put("valveOpen", avgOpen);
                    this.updateBuildUnitDataByAvgData(equipment, avgMap);
                }
            }
            //更新楼栋数据
            //判断该单元的楼栋是否有楼栋阀门，如果没有，则更新该楼栋所有单元数据至楼栋表，如果有，则不更新
            buildEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                    .eq(Equipment::getBuildId, buildId)
                    .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.BUILD_VALVE));
            if (CollectionUtils.isEmpty(buildEquipmentList)) {
                List<BuildUnit> buildUnitList = buildUnitService.list(Wrappers.<BuildUnit>lambdaQuery()
                        .eq(BuildUnit::getBuildId, buildId)
                        .ne(BuildUnit::getId, unitId));
                //获取楼栋下所有单元阀门开度平均值
                buildUnitList = buildUnitList.stream().filter(buildUnit -> buildUnit.getValveOpen() != null).collect(Collectors.toList());
                buildUnitList.add(unit);
                Integer sum = buildUnitList.stream().mapToInt(BuildUnit::getValveOpen).sum();
                Integer avgOpen = sum / buildUnitList.size();
                //更新楼栋阀门开度
                build.setValveOpen(avgOpen);
                build.setValveReadTime(DateUtils.getNowDate());
                //新增楼栋阀门开度实时数据和历史数据
                //新增单元阀门开度实时数据和历史数据
                avgMap = new HashMap<>();
                avgMap.put("valveOpen", avgOpen);
                buildService.updateById(build);
                this.updateBuildDataByAvgData(equipment, avgMap);
            }
            //更新小区数据
            //获取小区下的楼栋阀门开度平均值
            List<CBuild> cBuildList = cBuildService.list(Wrappers.<CBuild>lambdaQuery()
                    .eq(CBuild::getPlotId, plotId)
                    .ne(CBuild::getId, buildId));
            cBuildList = cBuildList.stream().filter(cBuild -> cBuild.getValveOpen() != null).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(cBuildList)) {
                cBuildList.add(build);
            }
            //获取小区下所有单元阀门开度平均值
            Integer sum = cBuildList.stream().filter(x -> x != null).mapToInt(CBuild::getValveOpen).sum();
            Integer avgOpen = sum / cBuildList.size();
            plot.setValveOpen(avgOpen);
            plot.setValveReadTime(DateUtils.getNowDate());

        } else {
            //判断住户对应的单元是否有热量表，如果没有，则更新该单元所有住户数据至单元表，如果有，则不更新
            buildUnitEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                    .eq(Equipment::getUnitId, unitId)
                    .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.UNIT_HEAT_METER));
            if (CollectionUtils.isEmpty(buildUnitEquipmentList)) {
                this.updateBuildUnitHeatByHousehold(equipment, unit, householdList);
            }

        }
    }

    /**
     * 根据住户热量数据更新单元数据
     * equipment    设备
     *
     * @param unit          单元
     * @param householdList 住户列表
     */
    private void updateBuildUnitHeatByHousehold(Equipment equipment, BuildUnit unit, List<Household> householdList) {
        //瞬时流量
        BigDecimal velocityFlow = null;

        //瞬时热量
        BigDecimal thermalPower = null;

        //累计热量
        BigDecimal currentHeatOrCold;

        //累计流量
        BigDecimal totalFlow;

        //供水温度
        BigDecimal waterSupplyTemperature = null;
        //回水温度
        BigDecimal returnWaterTemperature = null;
        //瞬时流量
        List<Household> velocityFlowUnitList = householdList.stream().filter(household -> household.getVelocityFlow() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(velocityFlowUnitList)) {
            velocityFlow = velocityFlowUnitList.stream().map(Household::getVelocityFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
            velocityFlow = velocityFlow.divide(new BigDecimal(velocityFlowUnitList.size()), 2, BigDecimal.ROUND_HALF_UP);
            unit.setVelocityFlow(velocityFlow);
        }

        List<Household> thermalPowerUnitList = householdList.stream().filter(household -> household.getThermalPower() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(thermalPowerUnitList)) {
            thermalPower = thermalPowerUnitList.stream().map(Household::getThermalPower).reduce(BigDecimal.ZERO, BigDecimal::add);
            thermalPower = thermalPower.divide(new BigDecimal(thermalPowerUnitList.size()), 2, BigDecimal.ROUND_HALF_UP);
            unit.setThermalPower(thermalPower);
        }

        //累计热量
        currentHeatOrCold = householdList.stream().filter(x -> x.getCurrentHeatOrCold() != null).map(Household::getCurrentHeatOrCold).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (currentHeatOrCold != null) {
            unit.setCurrentHeatOrCold(currentHeatOrCold);
        }

        //累计流量
        totalFlow = householdList.stream().filter(x -> x.getTotalFlow() != null).map(Household::getTotalFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (totalFlow != null) {
            unit.setTotalFlow(totalFlow);
        }

        List<Household> waterSupplyTemperatureUnitList = householdList.stream().filter(household -> household.getWaterSupplyTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(waterSupplyTemperatureUnitList)) {
            waterSupplyTemperature = waterSupplyTemperatureUnitList.stream().map(Household::getWaterSupplyTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            waterSupplyTemperature = waterSupplyTemperature.divide(new BigDecimal(waterSupplyTemperatureUnitList.size()), 2, BigDecimal.ROUND_HALF_UP);
            unit.setWaterSupplyTemperature(waterSupplyTemperature);
        }

        List<Household> returnWaterTemperatureUnitList = householdList.stream().filter(household -> household.getReturnWaterTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(returnWaterTemperatureUnitList)) {
            returnWaterTemperature = returnWaterTemperatureUnitList.stream().map(Household::getReturnWaterTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            returnWaterTemperature = returnWaterTemperature.divide(new BigDecimal(returnWaterTemperatureUnitList.size()), 2, BigDecimal.ROUND_HALF_UP);
            unit.setReturnWaterTemperature(returnWaterTemperature);
        }
        unit.setHeatReadTime(DateUtils.getNowDate());
        buildUnitService.updateById(unit);
        //新增单元热量表实时数据和历史数据
        Map<String, Object> avgMap = new HashMap<>();
        avgMap.put("totalFlow", totalFlow);
        avgMap.put("currentHeatOrCold", currentHeatOrCold);
        avgMap.put("thermalPower", thermalPower);
        avgMap.put("velocityFlow", velocityFlow);
        avgMap.put("returnWaterTemperature", returnWaterTemperature);
        avgMap.put("waterSupplyTemperature", waterSupplyTemperature);
        this.updateBuildUnitDataByAvgData(equipment, avgMap);

        //判断该单元的楼栋是否有热量表，如果没有，则更新该楼栋所有单元数据至楼栋表，如果有，则不更新
        List<Equipment> buildEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                .eq(Equipment::getBuildId, equipment.getBuildId())
                .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.BUILD_HEAT_METER));
        if (CollectionUtils.isEmpty(buildEquipmentList)) {
            this.updateBuildHeatByUnit(equipment);
        }
    }

    /**
     * 根据单元热量数据更新楼栋数据
     *
     * @param equipment
     */
    private void updateBuildHeatByUnit(Equipment equipment) {
        //瞬时流量
        BigDecimal velocityFlow = null;

        //瞬时热量
        BigDecimal thermalPower = null;

        //累计热量
        BigDecimal currentHeatOrCold;

        //累计流量
        BigDecimal totalFlow;

        //供水温度
        BigDecimal waterSupplyTemperature = null;
        //回水温度
        BigDecimal returnWaterTemperature = null;
        //更新楼栋数据(获取楼栋下单元数据的平均数)
        CBuild build = cBuildService.getById(equipment.getBuildId());
        List<BuildUnit> buildUnitList = buildUnitService.list(Wrappers.<BuildUnit>lambdaQuery()
                .eq(BuildUnit::getBuildId, equipment.getBuildId()));

        List<BuildUnit> velocityFlowList = buildUnitList.stream().filter(buildUnit -> buildUnit.getVelocityFlow() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(velocityFlowList)) {
            velocityFlow = velocityFlowList.stream().map(BuildUnit::getVelocityFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
            velocityFlow = velocityFlow.divide(new BigDecimal(velocityFlowList.size()), 2, BigDecimal.ROUND_HALF_UP);
            build.setVelocityFlow(velocityFlow);
        }
        List<BuildUnit> thermalPowerList = buildUnitList.stream().filter(buildUnit -> buildUnit.getThermalPower() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(thermalPowerList)) {
            thermalPower = thermalPowerList.stream().map(BuildUnit::getThermalPower).reduce(BigDecimal.ZERO, BigDecimal::add);
            thermalPower = thermalPower.divide(new BigDecimal(thermalPowerList.size()), 2, BigDecimal.ROUND_HALF_UP);
            build.setThermalPower(thermalPower);
        }

        List<BuildUnit> waterSupplyTemperatureList = buildUnitList.stream().filter(buildUnit -> buildUnit.getWaterSupplyTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(waterSupplyTemperatureList)) {
            waterSupplyTemperature = waterSupplyTemperatureList.stream().map(BuildUnit::getWaterSupplyTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            waterSupplyTemperature = waterSupplyTemperature.divide(new BigDecimal(waterSupplyTemperatureList.size()), 2, BigDecimal.ROUND_HALF_UP);
            build.setWaterSupplyTemperature(waterSupplyTemperature);
        }

        List<BuildUnit> returnWaterTemperatureList = buildUnitList.stream().filter(buildUnit -> buildUnit.getReturnWaterTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(returnWaterTemperatureList)) {
            returnWaterTemperature = returnWaterTemperatureList.stream().map(BuildUnit::getReturnWaterTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            returnWaterTemperature = returnWaterTemperature.divide(new BigDecimal(returnWaterTemperatureList.size()), 2, BigDecimal.ROUND_HALF_UP);
            build.setReturnWaterTemperature(returnWaterTemperature);
        }

        currentHeatOrCold = buildUnitList.stream().filter(x -> x.getCurrentHeatOrCold() != null).map(BuildUnit::getCurrentHeatOrCold).reduce(BigDecimal.ZERO, BigDecimal::add);
        totalFlow = buildUnitList.stream().filter(x -> x.getTotalFlow() != null).map(BuildUnit::getTotalFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
        build.setCurrentHeatOrCold(currentHeatOrCold);
        build.setVelocityFlow(velocityFlow);
        build.setReturnWaterTemperature(returnWaterTemperature);
        build.setWaterSupplyTemperature(waterSupplyTemperature);
        build.setTotalFlow(totalFlow);
        build.setHeatReadTime(DateUtils.getNowDate());
        buildService.updateById(build);
        this.updatePlotHeatByBuild(equipment);

        //新增楼栋热量表实时数据和历史数据
        Map<String, Object> avgMap = new HashMap<>();
        avgMap.put("totalFlow", totalFlow);
        avgMap.put("currentHeatOrCold", currentHeatOrCold);
        avgMap.put("thermalPower", thermalPower);
        avgMap.put("velocityFlow", velocityFlow);
        avgMap.put("returnWaterTemperature", returnWaterTemperature);
        avgMap.put("waterSupplyTemperature", waterSupplyTemperature);
        this.updateBuildDataByAvgData(equipment, avgMap);

    }

    private void updatePlotHeatByBuild(Equipment equipment) {
        //瞬时流量
        BigDecimal velocityFlow;

        //瞬时热量
        BigDecimal thermalPower;

        //累计热量
        BigDecimal currentHeatOrCold;

        //累计流量
        BigDecimal totalFlow;

        //供水温度
        BigDecimal waterSupplyTemperature;
        //回水温度
        BigDecimal returnWaterTemperature;
        CPlot plot = plotService.getById(equipment.getLotId());
        //更新小区数据(获取小区下楼栋数据的平均数)
        List<CBuild> buildList = cBuildService.list(Wrappers.<CBuild>lambdaQuery()
                .eq(CBuild::getPlotId, equipment.getLotId()));
        List<CBuild> velocityFlowBuildList = buildList.stream().filter(cBuild -> cBuild.getVelocityFlow() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(velocityFlowBuildList)) {
            velocityFlow = velocityFlowBuildList.stream().map(CBuild::getVelocityFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
            velocityFlow = velocityFlow.divide(new BigDecimal(velocityFlowBuildList.size()), 2, BigDecimal.ROUND_HALF_UP);
            plot.setVelocityFlow(velocityFlow);
        }
        List<CBuild> thermalPowerBuildList = buildList.stream().filter(cBuild -> cBuild.getThermalPower() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(thermalPowerBuildList)) {
            thermalPower = thermalPowerBuildList.stream().map(CBuild::getThermalPower).reduce(BigDecimal.ZERO, BigDecimal::add);
            thermalPower = thermalPower.divide(new BigDecimal(thermalPowerBuildList.size()), 2, BigDecimal.ROUND_HALF_UP);
            plot.setThermalPower(thermalPower);
        }
        List<CBuild> waterSupplyTemperatureBuildList = buildList.stream().filter(cBuild -> cBuild.getWaterSupplyTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(waterSupplyTemperatureBuildList)) {
            waterSupplyTemperature = waterSupplyTemperatureBuildList.stream().map(CBuild::getWaterSupplyTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            waterSupplyTemperature = waterSupplyTemperature.divide(new BigDecimal(waterSupplyTemperatureBuildList.size()), 2, BigDecimal.ROUND_HALF_UP);
            plot.setWaterSupplyTemperature(waterSupplyTemperature);
        }
        List<CBuild> returnWaterTemperatureBuildList = buildList.stream().filter(cBuild -> cBuild.getReturnWaterTemperature() != null).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(returnWaterTemperatureBuildList)) {
            returnWaterTemperature = returnWaterTemperatureBuildList.stream().map(CBuild::getReturnWaterTemperature).reduce(BigDecimal.ZERO, BigDecimal::add);
            returnWaterTemperature = returnWaterTemperature.divide(new BigDecimal(returnWaterTemperatureBuildList.size()), 2, BigDecimal.ROUND_HALF_UP);
            plot.setReturnWaterTemperature(returnWaterTemperature);
        }
        currentHeatOrCold = buildList.stream().filter(x -> x.getCurrentHeatOrCold() != null).map(CBuild::getCurrentHeatOrCold).reduce(BigDecimal.ZERO, BigDecimal::add);
        totalFlow = buildList.stream().filter(x -> x.getTotalFlow() != null).map(CBuild::getTotalFlow).reduce(BigDecimal.ZERO, BigDecimal::add);
        plot.setCurrentHeatOrCold(currentHeatOrCold);
        plot.setTotalFlow(totalFlow);
        plot.setHeatReadTime(DateUtils.getNowDate());
        plotService.updateById(plot);
    }

    /**
     * 根据单元数据更新
     *
     * @param equipment
     * @param map
     */
    public void updateUnitData(Equipment equipment, Map<String, Object> map) {
        BuildUnit unit = buildUnitService.getById(equipment.getUnitId());
        UpdateWrapper<BuildUnit> unitUpdateWrapper = new UpdateWrapper<>();
        String protocolType = equipment.getProtocolType();
        if (protocolType.equals(AgreementConstants.AgreementType.UNIT_VALVE)) {
            //阀门开度
            Integer valveOpen = 0;
            if (map.containsKey("valveOpen")) {
                valveOpen = Double.valueOf(map.get("valveOpen").toString()).intValue();
            } else if (map.containsKey("readOpenValue")) {
                valveOpen = Double.valueOf(map.get("readOpenValue").toString()).intValue();
            }
            if (valveOpen.compareTo(0) < 0 || valveOpen.compareTo(100) > 0) {
                LambdaQueryWrapper<AlarmSetting> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(AlarmSetting::getAlarmType, AgreementConstants.ExceptionType.TRANSFINITE_EXCEPTION);
                wrapper.eq(AlarmSetting::getIndexType, AgreementConstants.ControlTactics.ROOM_TEMPERATURE);
                AlarmSetting setting = alarmSettingService.getOne(wrapper);
                //阀门开度异常
                EquipmentAlarm alarm = new EquipmentAlarm();
                alarm.setPlotId(equipment.getLotId());
                alarm.setBuildId(equipment.getBuildId());
                alarm.setUnitId(equipment.getUnitId());
                alarm.setEquipmentId(equipment.getId());
                alarm.setAlarmSettingId(setting.getId());
                alarm.setHideOrPush(Integer.parseInt(setting.getPushStatus()));
                alarm.setPushNum(setting.getPushInterval());
                alarm.setRemark("设备【" + equipment.getEquipmentName() + "】开度超限异常");
                equipmentAlarmService.save(alarm);
                return;
            }
            unitUpdateWrapper.set("valve_open", valveOpen);
            unitUpdateWrapper.set("valve_read_time", DateUtils.getNowDate());
        } else {
            //瞬时流量
            BigDecimal velocityFlow = new BigDecimal(map.get("velocityFlow").toString());

            //瞬时热量
            BigDecimal thermalPower = new BigDecimal(map.get("thermalPower").toString());

            //累计热量
            BigDecimal currentHeatOrCold = new BigDecimal(map.get("currentHeatOrCold").toString());

            //累计流量
            BigDecimal totalFlow = new BigDecimal(map.get("totalFlow").toString());

            //供水温度
            BigDecimal waterSupplyTemperature = new BigDecimal(map.get("waterSupplyTemperature").toString());
            //回水温度
            BigDecimal returnWaterTemperature = new BigDecimal(map.get("returnWaterTemperature").toString());
            unitUpdateWrapper
                    .set(velocityFlow != null, "velocity_flow", velocityFlow)
                    .set(thermalPower != null, "thermal_power", thermalPower)
                    .set(currentHeatOrCold != null, "current_heat_or_cold", currentHeatOrCold)
                    .set(totalFlow != null, "total_flow", totalFlow)
                    .set(waterSupplyTemperature != null, "water_supply_temperature", waterSupplyTemperature)
                    .set(returnWaterTemperature != null, "return_water_temperature", returnWaterTemperature);
        }
        unitUpdateWrapper.eq("id", unit.getId());
        buildUnitService.update(unitUpdateWrapper);
        this.updateByUnit(equipment);
    }

    private void updateByUnit(Equipment equipment) {
        String protocolType = equipment.getProtocolType();
        List<Equipment> buildEquipmentList;
        Long unitId = equipment.getUnitId();
        Long buildId = equipment.getBuildId();
        Long plotId = equipment.getLotId();
        BuildUnit unit = buildUnitService.getById(unitId);
        CBuild build = cBuildService.getById(buildId);
        CPlot plot = plotService.getById(plotId);

        if (protocolType.equals(AgreementConstants.AgreementType.UNIT_VALVE)) {
            //更新楼栋数据
            //判断该单元的楼栋是否有楼栋阀门，如果没有，则更新该楼栋所有单元数据至楼栋表，如果有，则不更新
            buildEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                    .eq(Equipment::getBuildId, buildId)
                    .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.BUILD_VALVE));
            if (CollectionUtils.isEmpty(buildEquipmentList)) {
                List<BuildUnit> buildUnitList = buildUnitService.list(Wrappers.<BuildUnit>lambdaQuery()
                        .eq(BuildUnit::getBuildId, buildId));
                //获取楼栋下所有单元阀门开度平均值
                buildUnitList = buildUnitList.stream().filter(buildUnit -> buildUnit.getValveOpen() != null).collect(Collectors.toList());
                buildUnitList.add(unit);
                Integer sum = buildUnitList.stream().mapToInt(BuildUnit::getValveOpen).sum();
                Integer avgOpen = sum / buildUnitList.size();
                //更新楼栋阀门开度
                build.setValveOpen(avgOpen);
                build.setValveReadTime(DateUtils.getNowDate());
                //新增楼栋阀门开度实时数据和历史数据
                Map<String, Object> avgMap = new HashMap<>();
                avgMap.put("valveOpen", avgOpen);
                buildService.updateById(build);
                this.updateBuildDataByAvgData(equipment, avgMap);

            }
            //更新小区数据
            //获取小区下的楼栋阀门开度平均值
            List<CBuild> cBuildList = cBuildService.list(Wrappers.<CBuild>lambdaQuery()
                    .eq(CBuild::getPlotId, plotId)
                    .ne(CBuild::getId, buildId));
            cBuildList = cBuildList.stream().filter(cBuild -> cBuild.getValveOpen() != null).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(cBuildList)) {
                cBuildList.add(build);
            }
            //获取小区下所有单元阀门开度平均值
            Integer sum = cBuildList.stream().filter(x -> x != null).mapToInt(CBuild::getValveOpen).sum();
            Integer avgOpen = sum / cBuildList.size();
            plot.setValveOpen(avgOpen);
            plot.setValveReadTime(DateUtils.getNowDate());

        } else {
            //判断单元对应的楼栋是否有热量表，如果没有，则更新该楼栋所有单元数据至楼栋表，如果有，则不更新
            buildEquipmentList = equipmentService.list(Wrappers.<Equipment>lambdaQuery()
                    .eq(Equipment::getUnitId, unitId)
                    .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.BUILD_HEAT_METER));
            if (CollectionUtils.isEmpty(buildEquipmentList)) {
                this.updateBuildHeatByUnit(equipment);
            }
        }
        plotService.updateById(plot);
    }

    /**
     * 根据楼栋数据更新
     *
     * @param equipment
     * @param map
     */
    public void updateBuildData(Equipment equipment, Map<String, Object> map) {
        CBuild build = buildService.getById(equipment.getBuildId());
        UpdateWrapper<CBuild> buildUpdateWrapper = new UpdateWrapper<>();
        String protocolType = equipment.getProtocolType();
        if (protocolType.equals(AgreementConstants.AgreementType.BUILD_VALVE)){
            //阀门开度
            Integer valveOpen = 0;
            if (map.containsKey("valveOpen")) {
                valveOpen = Double.valueOf(map.get("valveOpen").toString()).intValue();
            } else if (map.containsKey("readOpenValue")) {
                valveOpen = Double.valueOf(map.get("readOpenValue").toString()).intValue();
            }
            if (valveOpen.compareTo(0) < 0 || valveOpen.compareTo(100) > 0) {
                LambdaQueryWrapper<AlarmSetting> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(AlarmSetting::getAlarmType, AgreementConstants.ExceptionType.TRANSFINITE_EXCEPTION);
                wrapper.eq(AlarmSetting::getIndexType, AgreementConstants.ControlTactics.ROOM_TEMPERATURE);
                AlarmSetting setting = alarmSettingService.getOne(wrapper);
                //阀门开度异常
                EquipmentAlarm alarm = new EquipmentAlarm();
                alarm.setPlotId(equipment.getLotId());
                alarm.setBuildId(equipment.getBuildId());
                alarm.setUnitId(equipment.getUnitId());
                alarm.setEquipmentId(equipment.getId());
                alarm.setAlarmSettingId(setting.getId());
                alarm.setHideOrPush(Integer.parseInt(setting.getPushStatus()));
                alarm.setPushNum(setting.getPushInterval());
                alarm.setRemark("设备【" + equipment.getEquipmentName() + "】开度超限异常");
                equipmentAlarmService.save(alarm);
                return;
            }
            buildUpdateWrapper.set("valve_open", valveOpen);
            buildUpdateWrapper.set("valve_read_time", DateUtils.getNowDate());
        }else {
            //瞬时流量
            BigDecimal velocityFlow = new BigDecimal(map.get("velocityFlow").toString());

            //瞬时热量
            BigDecimal thermalPower = new BigDecimal(map.get("thermalPower").toString());

            //累计热量
            BigDecimal currentHeatOrCold = new BigDecimal(map.get("currentHeatOrCold").toString());

            //累计流量
            BigDecimal totalFlow = new BigDecimal(map.get("totalFlow").toString());

            //供水温度
            BigDecimal waterSupplyTemperature = new BigDecimal(map.get("waterSupplyTemperature").toString());
            //回水温度
            BigDecimal returnWaterTemperature = new BigDecimal(map.get("returnWaterTemperature").toString());
            buildUpdateWrapper
                    .set(velocityFlow != null, "velocity_flow", velocityFlow)
                    .set(thermalPower != null, "thermal_power", thermalPower)
                    .set(currentHeatOrCold != null, "current_heat_or_cold", currentHeatOrCold)
                    .set(totalFlow != null, "total_flow", totalFlow)
                    .set(waterSupplyTemperature != null, "water_supply_temperature", waterSupplyTemperature)
                    .set(returnWaterTemperature != null, "return_water_temperature", returnWaterTemperature);
        }
        buildUpdateWrapper.eq("id", build.getId());
        buildService.update(buildUpdateWrapper);
    }


    /**
     * 获取到住户数据且对应的单元没有设备时，新增单元实时表数据和单元历史表数据
     *
     * @param equipment 设备
     * @param map       数据
     */
    private void updateBuildUnitDataByAvgData(Equipment equipment, Map<String, Object> map) {
        JSONObject jsonObject;
        String protocolType = equipment.getProtocolType();
        //新增单元热量表实时数据和历史数据
        if (protocolType.equals(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER)) {
            jsonObject = new JSONObject();
            jsonObject.put("totalFlow", new BigDecimal(String.valueOf(map.get("totalFlow"))));
            jsonObject.put("currentHeatOrCold", new BigDecimal(String.valueOf(map.get("currentHeatOrCold"))));
            jsonObject.put("thermalPower", new BigDecimal(String.valueOf(map.get("thermalPower"))));
            jsonObject.put("velocityFlow", new BigDecimal(String.valueOf(map.get("velocityFlow"))));
            jsonObject.put("returnWaterTemperature", new BigDecimal(String.valueOf(map.get("returnWaterTemperature"))));
            jsonObject.put("waterSupplyTemperature", new BigDecimal(String.valueOf(map.get("waterSupplyTemperature"))));
            //判断是否有该单元实时数据
            AgreementHeat heat = heatService.getOne(Wrappers.<AgreementHeat>lambdaQuery()
                    .eq(AgreementHeat::getProtocolType, AgreementConstants.AgreementType.UNIT_HEAT_METER)
                    .eq(AgreementHeat::getUnitId, equipment.getUnitId()));
            if(heat == null){
                heat = new AgreementHeat();
            }
            heat.setDeviceInstructionId(0L);
            heat.setDtuId(0L);
            heat.setProtocolType(AgreementConstants.AgreementType.UNIT_HEAT_METER);
            heat.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_HEAT_METER);
            heat.setInstructType("1");
            heat.setInstructName("读 热量表数据");
            heat.setPlotId(equipment.getLotId());
            heat.setBuildId(equipment.getBuildId());
            heat.setUnitId(equipment.getUnitId());
            heat.setDeviceType("20");
            heat.setDataFieldSerialNumber("0");
            heat.setInstructionSet("0");
            heat.setJsonData(jsonObject.toJSONString());
            heatService.saveOrUpdate(heat);


            AgreementHeatHistory heatHistory = new AgreementHeatHistory();
            heatHistory.setDeviceInstructionId(0L);
            heatHistory.setDtuId(0L);
            heatHistory.setProtocolType(AgreementConstants.AgreementType.UNIT_HEAT_METER);
            heatHistory.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_HEAT_METER);
            heatHistory.setInstructType("1");
            heatHistory.setInstructName("读 热量表数据");
            heatHistory.setPlotId(equipment.getLotId());
            heatHistory.setBuildId(equipment.getBuildId());
            heatHistory.setUnitId(equipment.getUnitId());
            heatHistory.setPrefix("0");
            heatHistory.setStartChar("0");
            heatHistory.setDeviceType("20");
            heatHistory.setControlCode("0");
            heatHistory.setLengthField("0");
            heatHistory.setDataFieldMark("0");
            heatHistory.setDataFieldSerialNumber("0");
            heatHistory.setEndMark("0");
            heatHistory.setInstructionSet("0");
            heatHistory.setJsonData(jsonObject.toJSONString());
            heatHistoryService.save(heatHistory);
        } else {
            //新增单元阀门实时和历史数据
            jsonObject = new JSONObject();
            jsonObject.put("readOpenValue", map.get("valveOpen"));

            AgreementUnitValve valve = unitValveService.getOne(Wrappers.<AgreementUnitValve>lambdaQuery()
                    .eq(AgreementUnitValve::getUnitId, equipment.getUnitId()));
            if (valve == null) {
                valve = new AgreementUnitValve();
            }
            valve.setDeviceInstructionId(0L);
            valve.setDtuId(0L);
            valve.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_HEAT_METER);
            valve.setInstructType("1");
            valve.setInstructName("读系统信息");
            valve.setPlotId(equipment.getLotId());
            valve.setBuildId(equipment.getBuildId());
            valve.setUnitId(equipment.getUnitId());
            valve.setDeviceType("40");
            valve.setDataFieldSerialNumber("0");
            valve.setInstructionSet("0");
            valve.setJsonData(jsonObject.toJSONString());
            unitValveService.saveOrUpdate(valve);


            AgreementUnitValveHistory agreementUnitValveHistory = new AgreementUnitValveHistory();
            agreementUnitValveHistory.setDeviceInstructionId(0L);
            agreementUnitValveHistory.setDtuId(0L);
            agreementUnitValveHistory.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_VALVE);
            agreementUnitValveHistory.setInstructType("1");
            agreementUnitValveHistory.setInstructName("读系统信息");
            agreementUnitValveHistory.setPlotId(equipment.getLotId());
            agreementUnitValveHistory.setBuildId(equipment.getBuildId());
            agreementUnitValveHistory.setUnitId(equipment.getUnitId());
            agreementUnitValveHistory.setPrefix("0");
            agreementUnitValveHistory.setStartChar("0");
            agreementUnitValveHistory.setDeviceType("40");
            agreementUnitValveHistory.setControlCode("0");
            agreementUnitValveHistory.setLengthField("0");
            agreementUnitValveHistory.setDataFieldMark("0");
            agreementUnitValveHistory.setDataFieldSerialNumber("0");
            agreementUnitValveHistory.setEndMark("0");
            agreementUnitValveHistory.setInstructionSet("0");

            agreementUnitValveHistory.setJsonData(jsonObject.toJSONString());
            unitValveHistoryService.save(agreementUnitValveHistory);

            BuildUnit buildUnit = buildUnitService.getById(equipment.getUnitId());
            buildUnit.setValveOpen(Integer.parseInt(map.get("valveOpen").toString()));
            buildUnit.setValveReadTime(DateUtils.getNowDate());
            buildUnitService.updateById(buildUnit);
        }
    }

    /**
     * 下级设备获取到数据时，楼栋没有设备，新增楼栋实时表数据和楼栋历史表数据
     */
    private void updateBuildDataByAvgData(Equipment equipment, Map<String, Object> map) {

        String protocolType = equipment.getProtocolType();
        if (protocolType.equals(AgreementConstants.AgreementType.UNIT_HEAT_METER) || protocolType.equals(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER)) {
            //判断是否有楼栋热量实时数据
            AgreementHeat heat = heatService.getOne(Wrappers.<AgreementHeat>lambdaQuery()
                    .eq(AgreementHeat::getProtocolType , AgreementConstants.AgreementType.BUILD_HEAT_METER)
                    .eq(AgreementHeat::getBuildId , equipment.getBuildId()));
            if(heat == null){
                heat = new AgreementHeat();
            }
            heat.setDeviceInstructionId(0L);
            heat.setDtuId(0L);
            heat.setProtocolType(AgreementConstants.AgreementType.BUILD_HEAT_METER);
            heat.setProtocolName(AgreementConstants.AgreementTypeName.BUILD_HEAT_METER);
            heat.setInstructType("1");
            heat.setInstructName("读 热量表数据");
            heat.setPlotId(equipment.getLotId());
            heat.setBuildId(equipment.getBuildId());
            heat.setDeviceType("20");
            heat.setDataFieldSerialNumber("0");
            heat.setInstructionSet("0");
            heatService.saveOrUpdate(heat);

            AgreementHeatHistory heatHistory = new AgreementHeatHistory();
            heatHistory.setDeviceInstructionId(0L);
            heatHistory.setDtuId(0L);
            heatHistory.setProtocolType(AgreementConstants.AgreementType.BUILD_HEAT_METER);
            heatHistory.setProtocolName(AgreementConstants.AgreementTypeName.BUILD_HEAT_METER);
            heatHistory.setInstructType("1");
            heatHistory.setInstructName("读 热量表数据");
            heatHistory.setPlotId(equipment.getLotId());
            heatHistory.setBuildId(equipment.getBuildId());
            heatHistory.setPrefix("0");
            heatHistory.setStartChar("0");
            heatHistory.setDeviceType("20");
            heatHistory.setControlCode("0");
            heatHistory.setLengthField("0");
            heatHistory.setDataFieldMark("0");
            heatHistory.setDataFieldSerialNumber("0");
            heatHistory.setEndMark("0");
            heatHistory.setInstructionSet("0");

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("totalFlow", new BigDecimal(String.valueOf(map.get("thermalPower"))));
            jsonObject.put("currentHeatOrCold", new BigDecimal(String.valueOf(map.get("currentHeatOrCold"))));
            jsonObject.put("thermalPower", new BigDecimal(String.valueOf(map.get("thermalPower"))));
            jsonObject.put("velocityFlow", new BigDecimal(String.valueOf(map.get("velocityFlow"))));
            jsonObject.put("returnWaterTemperature", new BigDecimal(String.valueOf(map.get("returnWaterTemperature"))));
            jsonObject.put("waterSupplyTemperature", new BigDecimal(String.valueOf(map.get("waterSupplyTemperature"))));

            heatHistory.setJsonData(jsonObject.toJSONString());
            heatHistoryService.save(heatHistory);
        } else {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("readOpenValue", map.get("valveOpen"));
//            //判断是否有楼栋阀门实时数据
            AgreementBuildValve valve = buildValveService.getOne(Wrappers.<AgreementBuildValve>lambdaQuery()
                    .eq(AgreementBuildValve::getBuildId , equipment.getBuildId()));
            if(valve == null){
                valve = new AgreementBuildValve();
            }
            valve.setDeviceInstructionId(0L);
            valve.setDtuId(0L);
            valve.setProtocolName(AgreementConstants.AgreementTypeName.BUILD_VALVE);
            valve.setInstructType("1");
            valve.setInstructName("读系统信息");
            valve.setPlotId(equipment.getLotId());
            valve.setBuildId(equipment.getBuildId());
            valve.setDeviceType("20");
            valve.setDataFieldSerialNumber("0");
            valve.setJsonData(jsonObject.toJSONString());
            valve.setInstructionSet("0");
            buildValveService.saveOrUpdate(valve);


            AgreementBuildValveHistory buildValveHistory = new AgreementBuildValveHistory();
            buildValveHistory.setDeviceInstructionId(0L);
            buildValveHistory.setDtuId(0L);
            buildValveHistory.setProtocolName(AgreementConstants.AgreementTypeName.BUILD_VALVE);
            buildValveHistory.setInstructType("1");
            buildValveHistory.setInstructName("读系统信息");
            buildValveHistory.setPlotId(equipment.getLotId());
            buildValveHistory.setBuildId(equipment.getBuildId());
            buildValveHistory.setPrefix("0");
            buildValveHistory.setStartChar("0");
            buildValveHistory.setDeviceType("20");
            buildValveHistory.setControlCode("0");
            buildValveHistory.setLengthField("0");
            buildValveHistory.setDataFieldMark("0");
            buildValveHistory.setDataFieldSerialNumber("0");
            buildValveHistory.setEndMark("0");
            buildValveHistory.setInstructionSet("0");
            buildValveHistory.setJsonData(jsonObject.toJSONString());
            buildValveHistoryService.save(buildValveHistory);
        }
    }
}
